package com.hzy.filter;

import com.hzy.infrastructure.config.AdminAppConfig;
import com.hzy.infrastructure.annotation.AdminActionDescribe;
import com.hzy.infrastructure.annotation.AdminControllerDescriptor;
import com.hzy.infrastructure.exception.ApiResult;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.hzy.infrastructure.Tools;
import com.hzy.infrastructure.security.JwtTokenUtils;
import com.hzy.system.domain.SysUser;
import com.hzy.system.service.IAccountService;
import com.hzy.system.service.ISysMenuService;
import com.hzy.system.service.ISysOperationLogService;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * <p>
 * 请求 过滤器
 * </p>
 *
 * @author hzy
 * @since 2020-04-26
 */
public class AdminAuthorizationFilterHandlerInterceptor implements HandlerInterceptor {
    private final String logOutMessage = "未授权，请登陆授权！";
    private final String logOutPath = "/admin/login";
    private final ISysMenuService sysMenuService;
    private final AdminAppConfig adminAppConfig;
    private final IAccountService accountService;
    private final ISysOperationLogService sysOperationLogService;

    public AdminAuthorizationFilterHandlerInterceptor(ISysMenuService sysMenuService, AdminAppConfig adminAppConfig, IAccountService accountService, ISysOperationLogService sysOperationLogService) {
        this.sysMenuService = sysMenuService;
        this.adminAppConfig = adminAppConfig;
        this.accountService = accountService;
        this.sysOperationLogService = sysOperationLogService;
    }

    /**
     * 处理 HandlerAdapte 业务 之前调用
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    @ResponseBody
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 判断是否 java 对象
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        // 获取 授权 注解
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 先找 类 中 是否有 注解
        Class<?> classMethod = method.getDeclaringClass();
        AdminControllerDescriptor adminAuthorization = classMethod.getAnnotation(AdminControllerDescriptor.class);
        // 如果 类 上面 没有 注解 则 函数体上面找
        if (Objects.isNull(adminAuthorization)) {
            adminAuthorization = method.getAnnotation(AdminControllerDescriptor.class);
        }
        // 如果添加了 AdminAuthorization 注解 并且 authCheck = true 表示检测
        if (Objects.nonNull(adminAuthorization) && adminAuthorization.authCheck()) {
            return this.checkAuth(request, response, handler);
        }

        // 判断 函数是否有 权限检查 注解
        AdminActionDescribe adminActionDescribe = method.getAnnotation(AdminActionDescribe.class);
        if (Objects.isNull(adminActionDescribe)) {
            return true;
        }

        if (Objects.isNull(adminAuthorization)) {
            return true;
        }

        Integer menuId = adminAuthorization.value();

        Map<String, Boolean> maps = this.sysMenuService.getPowerStateByMenuId(menuId);
        if (Objects.isNull(maps)) {
            return true;
        }

        String value = adminActionDescribe.value();
        if (ObjectUtils.isEmpty(value)) {
            return false;
        }

//        var map = maps.entrySet().stream().filter(w -> w.getKey().equals(value)).findFirst();
//        if (map.isPresent() && !map.get().getValue()) {
//            Tools.contentResult(response, new StringBuilder("无权访问!"), "text/html; charset=utf-8");
//            return false;
//        }

        return true;
    }

    /**
     * 处理 HandlerAdapte 业务 之后调用
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 请求处理 业务 完成后回调
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        // 判断是否 java 对象
        if (!(handler instanceof HandlerMethod)) {
            return;
        }

        // 屏蔽错误页面
        if ("/error".equals(request.getServletPath())) {
            return;
        }
    }

    /**
     * 授权 检查
     *
     * @param request
     * @param response
     * @param handler
     * @return
     */
    private boolean checkAuth(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 验证 token
        String tokenValue = this.accountService.getToken();
        if (Objects.isNull(tokenValue)) {
            this.resultUnAuth(response);
            return false;
        }

        // 验证 token 是否有效
        SysUser sysUser = JwtTokenUtils.unSign(tokenValue, SysUser.class);

        if (sysUser == null) {
            this.resultUnAuth(response);
            return false;
        }

        this.accountService.getAccountContext();

        return true;
    }

    /**
     * 返回未授权Json
     *
     * @param response
     * @throws Exception
     */
    private void resultUnAuth(HttpServletResponse response) throws Exception {
        ApiResult<String> data = new ApiResult<>(ApiResult.StatusCodeEnum.UnAuth, logOutMessage, logOutPath);
        Tools.jsonResult(response, data);
    }

}
